//
//  main.c
//  IdeVariable
//
//  Created by 李栋 on 15/12/13.
//  Copyright © 2015年 李栋. All rights reserved.
//
/********************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#define true 1
#define false 0
#define structSize sizeof(struct variableList)
/********************************************************/
struct variableList
{
    char type;
    char* variableName;
    union
    {
        int intVaule;
        double doubleVaule;
    }variableValue;
    struct variableList* next;
}variable;
/********************************************************/
struct variableList* variableListHead = NULL;
//用于存放链表头
void initVariableList(char* variableName,char type,...);
//初始化列表方法
void emptyVariableList();
//清空列表方法
int isEmptyVariableList();
//判断空链表方法
void addNode(char* variableName,char type,...);
//在链表末尾添加节点方法
void dealLastNode();
//删除链表末尾节点方法
struct variableList* getLastNode();
//得到链表最后节点方法
void delVariableListNode(int nodeIndex);
//删除链表指定节点方法
void insertVariableListNode(int nodeIndex,char* variableName,char type,...);
//插入链表指定节点方法
struct variableList* getVariableListNode(int nodeIndex);
//得到链表指定节点方法
int getNodeNumber();
//链表节点数计算方法
struct variableList* searchVariable(char* variableName);
//指定变量搜索方法
/********************************************************/
int main(int argc, const char * argv[]){
    initVariableList("a", 'i',1);
    addNode("b", 'i',2);
    printf("%d\n",getNodeNumber());
    printf("%d\n",getLastNode()->variableValue.intVaule);
    return 0;
}
/********************************************************/
/**
 初始化变量链表
 
 - returns: 空
 */
void initVariableList(char* variableName,char type,...){
    va_list arg_ptr;
    struct variableList* firstNode;
    firstNode = (struct variableList*)malloc(structSize);
    va_start(arg_ptr, type);
    if (type == 'i') {
        firstNode->variableValue.intVaule = va_arg(arg_ptr, int);
    }else{
        firstNode->variableValue.doubleVaule = va_arg(arg_ptr, double);
    }
    firstNode->type = type;
    firstNode->variableName = variableName;
    firstNode->next = NULL;
    variableListHead = firstNode;
}

/**
 *  置空变量链表
 */
void emptyVariableList(){
    variableListHead = NULL;
}

/**
 *  判断链表是否为空
 *
 *  @return 是/否
 */
int isEmptyVariableList(){
    return variableListHead==NULL?true:false;
}

/**
 *  在链表最后添加一个节点方法
 *
 *  @param variableName 变量名
 *  @param type         变量类型
 *  @param ...          变量值
 */
void addNode(char* variableName,char type,...){
    va_list arg_ptr;
    struct variableList* lastNode;
    struct variableList* nextNode;
    va_start(arg_ptr, type);
    if (isEmptyVariableList()) {
        if (type == 'i') {
            initVariableList(variableName, type,va_arg(arg_ptr, int));
        }
        else{
            initVariableList(variableName, type,va_arg(arg_ptr, double));
        }
    }
    else {
        lastNode = getLastNode();
        nextNode = (struct variableList*)malloc(structSize);
        lastNode->next = nextNode;
        nextNode->variableName = variableName;
        nextNode->type = type;
        if (type == 'i') {
            nextNode->variableValue.intVaule = va_arg(arg_ptr, int);
        }else {
            nextNode->variableValue.doubleVaule = va_arg(arg_ptr, double);
        }
    }
    
}

/**
 *  删除链表最后一个节点方法
 */
void dealLastNode(){
    struct variableList* lastNode = variableListHead;
    while (NULL != lastNode->next->next ) {
        lastNode = lastNode->next;
    }
    lastNode->next = NULL;
}

/**
 *  得到链表最后一个节点方法
 *
 *  @return 链表最后一个节点
 */
struct variableList* getLastNode(){
    struct variableList* LastNode = variableListHead;
    for (int i = 1; i < getNodeNumber(); i++) {
        LastNode = LastNode->next;
    }
    return LastNode;
}

/**
 *  删除链表指定节点方法
 *
 *  @param nodeIndex 待删除节点索引
 */
void delVariableListNode(int nodeIndex){
    struct variableList* dealNode = variableListHead;
    struct variableList* previousNode = NULL;
    if (nodeIndex == 1) {
        variableListHead = dealNode->next;
        return;
    }
    for (int i = 1; i < nodeIndex; i++) {
        if (i == nodeIndex-1) {
            previousNode = dealNode;
        }
        dealNode = dealNode->next;
    }
    if (dealNode->next == NULL) {
        previousNode->next = NULL;
    }
    previousNode->next = dealNode->next;
}

/**
 *  在链表指定位置处插入节点
 *
 *  @param nodeIndex    指定位置
 *  @param variableName 变量名
 *  @param type         变量类型
 *  @param ...          变量值
 */
void insertVariableListNode(int nodeIndex,char* variableName,char type,...){
    va_list arg_ptr;
    va_start(arg_ptr, type);
    struct variableList* inseartedNode = (struct variableList*)malloc(structSize);
    struct variableList* previousNode = variableListHead;
    struct variableList* nextNode;
    for (int i = 1; i < nodeIndex-1; i++) {
        previousNode = previousNode->next;
    }
    nextNode = previousNode->next;
    previousNode->next = inseartedNode;
    inseartedNode->next = nextNode;
    inseartedNode->variableName = variableName;
    inseartedNode->type = type;
    if (type == 'i') {
        initVariableList(variableName, type,va_arg(arg_ptr, int));
    }
    else{
        initVariableList(variableName, type,va_arg(arg_ptr, double));
    }
}

/**
 *  得到链表指定节点方法
 *
 *  @param nodeIndex 指定节点索引
 *
 *  @return 链表指定节点
 */
struct variableList* getVariableListNode(int nodeIndex){
    struct variableList* wantedNode = variableListHead;
    for (int i = 1; i < nodeIndex; i++) {
        wantedNode = wantedNode->next;
    }
    return wantedNode;
}

/**
 *  计算链表节点个数方法
 *
 *  @return 链表节点个数
 */
int getNodeNumber(){
    int i = 1;
    if (isEmptyVariableList()) {
        return 0;
    }
    struct variableList* tempNode = variableListHead;
    while (NULL != tempNode->next) {
        i++;
        tempNode = tempNode->next;
    }
    return i;
}

/**
 *  按指定变量名搜索变量
 *
 *  @param variableName 指定变量名
 *
 *  @return 想要的变量，包含变量名，类型，数值（未找到则返回NULL）
 */
struct variableList* searchVariable(char* variableName){
    struct variableList* wantedVariable = variableListHead;
    while (NULL != wantedVariable->next ) {
        if(strcmp(variableName, wantedVariable->variableName)){
            return wantedVariable;
        }else {
            wantedVariable = wantedVariable->next;
        }
    }
    return NULL;
}

/********************************************************/
